﻿using System.Xml;
using System.Data;

namespace ZXW.DotNet.Common.Core.Xml
{
    /// <summary>
    /// XML 文件操作
    /// </summary>
    public class XmlHelper

    {
        /// <summary>
        /// 读取XML资源到DataSet中
        /// </summary>
        /// <param name="source">XML资源，文件为路径，否则为XML字符串</param>
        /// <param name="xmlType">XML资源类型(File/String)</param>
        /// <returns>DataSet</returns>
        public static DataSet GetDataSet(string source, XmlType xmlType)
        {
            var ds = new DataSet();
            if (xmlType == XmlType.File)
            {
                ds.ReadXml(source);
            }
            else
            {
                var xd = new XmlDocument();
                xd.LoadXml(source);
                var xnr = new XmlNodeReader(xd);
                ds.ReadXml(xnr);
            }
            return ds;
        }

        /// <summary>
        /// 获取一个字符串xml文档中的 DataSet
        /// </summary>
        /// <param name="xmlString">含有xml信息的字符串</param>
        /// <param name="ds" />
        public static void GetXmlValueDs(string xmlString, ref DataSet ds)
        {
            var xd = new XmlDocument();
            xd.LoadXml(xmlString);
            var xnr = new XmlNodeReader(xd);
            ds.ReadXml(xnr);
            xnr.Close();
        }

        /// <summary>
        /// 读取XML资源到DataTable中
        /// </summary>
        /// <param name="source">XML资源，文件为路径，否则为XML字符串</param>
        /// <param name="xmlType">XML资源类型：文件，字符串</param>
        /// <param name="tableName">表名称</param>
        /// <returns>DataTable</returns>
        public static DataTable GetTable(string source, XmlType xmlType, string tableName)
        {
            var ds = new DataSet();
            if (xmlType == XmlType.File)
            {
                ds.ReadXml(source);
            }
            else
            {
                XmlDocument xd = new XmlDocument();
                xd.LoadXml(source);
                XmlNodeReader xnr = new XmlNodeReader(xd);
                ds.ReadXml(xnr);
            }
            return ds.Tables[tableName];
        }


        /// <summary>
        /// 读取XML资源中指定的DataTable的指定行指定列的值
        /// </summary>
        /// <param name="source">XML资源</param>
        /// <param name="xmlType">XML资源类型：文件，字符串</param>
        /// <param name="tableName">表名</param>
        /// <param name="rowIndex">行号</param>
        /// <param name="colName">列名</param>
        /// <returns>值，不存在时返回Null</returns>
        public static object GetTableCell(string source, XmlType xmlType, string tableName, int rowIndex, string colName)
        {
            DataSet ds = new DataSet();
            if (xmlType == XmlType.File)
            {
                ds.ReadXml(source);
            }
            else
            {
                XmlDocument xd = new XmlDocument();
                xd.LoadXml(source);
                XmlNodeReader xnr = new XmlNodeReader(xd);
                ds.ReadXml(xnr);
            }
            return ds.Tables[tableName].Rows[rowIndex][colName];
        }

        /// <summary>
        /// 读取XML资源中指定的DataTable的指定行指定列的值
        /// </summary>
        /// <param name="source">XML资源</param>
        /// <param name="xmlType">XML资源类型：文件，字符串</param>
        /// <param name="tableName">表名</param>
        /// <param name="rowIndex">行号</param>
        /// <param name="colIndex">列号</param>
        /// <returns>值，不存在时返回Null</returns>
        public static object GetTableCell(string source, XmlType xmlType, string tableName, int rowIndex, int colIndex)
        {
            DataSet ds = new DataSet();
            if (xmlType == XmlType.File)
            {
                ds.ReadXml(source);
            }
            else
            {
                XmlDocument xd = new XmlDocument();
                xd.LoadXml(source);
                XmlNodeReader xnr = new XmlNodeReader(xd);
                ds.ReadXml(xnr);
            }
            return ds.Tables[tableName].Rows[rowIndex][colIndex];
        }

        /// <summary>
        /// 获取一个字符串xml文档中的一个table，指定行，指定列的值
        /// </summary>
        /// <param name="xmlString">含有xml信息的字符串</param>
        /// <param name="tablename">表名</param>
        /// <param name="rowIndex">指定行</param>
        /// <param name="colName">指定列名</param>
        /// <returns>相应节点的值</returns>
        public static string GetXmlValue(string xmlString, string tablename, int rowIndex, string colName)
        {
            var xd = new XmlDocument();
            xd.LoadXml(xmlString);
            XmlElement root = xd.DocumentElement;
            if (root != null)
            {

                XmlNode xe = root.SelectNodes(tablename).Item(rowIndex);

                string val = "";
                if (null != xe)
                {
                    foreach (XmlNode xn in xe.ChildNodes)
                    {
                        if (xn.LocalName == colName)
                        {
                            val = xn.InnerText;
                            break;
                        }
                    }
                    return val;
                }
                return null;
            }
            return null;
        }

        /// <summary>
        /// 获取一个xml文件中的一个table，指定行，指定列的值
        /// </summary>
        /// <param name="xmlString">含有xml信息的字符串</param>
        /// <param name="tablename">表名</param>
        /// <param name="rowIndex">指定行</param>
        /// <param name="colName">指定列名</param>
        /// <param name="isfile" />
        /// <returns>相应节点的值</returns>
        public static string GetXmlValue(string xmlString, string tablename, int rowIndex, string colName, bool isfile)
        {
            var xd = new XmlDocument();
            if (isfile)
                xd.Load(xmlString);
            else
                xd.LoadXml(xmlString);
            XmlElement root = xd.DocumentElement;
            if (root != null)
            {
                XmlNode xe = root.SelectNodes(tablename).Item(rowIndex);

                string val = "";
                if (null == xe)
                {
                    return "";
                }
                foreach (XmlNode xn in xe.ChildNodes)
                {
                    if (xn.LocalName == colName)
                    {
                        val = xn.InnerText;
                        break;
                    }
                }
                return val;
            }
            return null;
        }

        /// <summary>
        /// 获取一个字符串xml文档中的dt
        /// </summary>
        /// <param name="xmlString">含有xml信息的字符串</param>
        /// <param name="dt"></param>
        /// <param name="tableName"></param>
        public static void GetXmlValueDt(string xmlString, ref DataTable dt, string tableName)
        {
            DataSet ds = new DataSet();
            XmlDocument xd = new XmlDocument();
            xd.LoadXml(xmlString);
            XmlNodeReader xnr = new XmlNodeReader(xd);
            ds.ReadXml(xnr);
            xnr.Close();
            dt = ds.Tables[tableName];
        }

        /// <summary>
        /// 将DataTable写入XML文件中
        /// </summary>
        /// <param name="dt">含有数据的DataTable</param>
        /// <param name="filePath">文件路径</param>
        public static int SaveTableToFile(DataTable dt, string filePath)
        {
            DataSet ds = new DataSet("Config");
            ds.Tables.Add(dt.Copy());

            try
            {
                ds.WriteXml(filePath);
            }
            catch
            {
                return 0;
            }
            return 1;
        }

        /// <summary>
        /// 将DataTable以指定的根结点名称写入文件
        /// </summary>
        /// <param name="dt">含有数据的DataTable</param>
        /// <param name="rootName">根结点名称</param>
        /// <param name="filePath">文件路径</param>
        public static int SaveTableToFile(DataTable dt, string rootName, string filePath)
        {
            DataSet ds = new DataSet(rootName);
            ds.Tables.Add(dt.Copy());

            try
            {
                ds.WriteXml(filePath);
            }
            catch
            {
                return 0;
            }
            return 1;
        }

        /// <summary>
        /// 使用DataSet方式更新XML文件节点
        /// </summary>
        /// <param name="filePath">XML文件路径</param>
        /// <param name="tableName">表名称</param>
        /// <param name="rowIndex">行号</param>
        /// <param name="colName">列名</param>
        /// <param name="content">更新值</param>
        /// <returns>更新是否成功</returns>
        public static bool UpdateTableCell(string filePath, string tableName, int rowIndex, string colName, string content)
        {
            bool flag;
            DataSet ds;
            using (ds = new DataSet())
            {
                ds.ReadXml(filePath);
                var dt = ds.Tables[tableName];

                if (dt.Rows[rowIndex][colName] != null)
                {
                    dt.Rows[rowIndex][colName] = content;
                    ds.WriteXml(filePath);
                    flag = true;
                }
                else
                {
                    flag = false;
                }
            }

            return flag;
        }

        /// <summary>
        /// 使用DataSet方式更新XML文件节点
        /// </summary>
        /// <param name="filePath">XML文件路径</param>
        /// <param name="tableName">表名称</param>
        /// <param name="rowIndex">行号</param>
        /// <param name="colIndex"></param>
        /// <param name="content">更新值</param>
        /// <returns>更新是否成功</returns>
        public static bool UpdateTableCell(string filePath, string tableName, int rowIndex, int colIndex, string content)
        {
            bool flag = false;
            DataSet ds = new DataSet();
            ds.ReadXml(filePath);
            DataTable dt = ds.Tables[tableName];

            if (dt.Rows[rowIndex][colIndex] != null)
            {
                dt.Rows[rowIndex][colIndex] = content;
                ds.WriteXml(filePath);
                flag = true;
            }

            return flag;
        }

        /// <summary>
        /// 使用DataSet方式更新XML文件节点
        /// </summary>
        /// <returns>更新是否成功</returns>
        public static object GetNodeValue(string source, XmlType xmlType, string nodeName)
        {
            XmlDocument xd = new XmlDocument();
            if (xmlType == XmlType.File)
            {
                xd.Load(source);
            }
            else
            {
                xd.LoadXml(source);
            }
            XmlElement xe = xd.DocumentElement;
            if (xe != null)
            {
                XmlNode xn = xe.SelectSingleNode("//" + nodeName);
                if (xn != null)
                {
                    return xn.InnerText;
                }
            }
            return null;
        }

        /// <summary>
        /// 读取XML资源中的指定节点内容
        /// </summary>
        /// <param name="source">XML资源</param>
        /// <param name="nodeName">节点名称</param>
        /// <returns>节点内容</returns>
        public static object GetNodeValue(string source, string nodeName)
        {
            if ((string.IsNullOrEmpty(source) || string.IsNullOrEmpty(nodeName)) || source.Length < nodeName.Length*2)
            {
                return null;
            }

            var start = source.IndexOf("<" + nodeName + ">") + nodeName.Length + 2;
            var end = source.IndexOf("</" + nodeName + ">");

            return start == -1 || end == -1 ? null : (start >= end ? null : source.Substring(start, end - start));
        }

        /// <summary>
        /// 更新XML文件中的指定节点内容
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="nodeName">节点名称</param>
        /// <param name="nodeValue">更新内容</param>
        /// <returns>更新是否成功</returns>
        public static bool UpdateNode(string filePath, string nodeName, string nodeValue)
        {
            bool flag = false;
            XmlDocument xd = new XmlDocument();
            xd.Load(filePath);
            XmlElement xe = xd.DocumentElement;
            if (xe != null)
            {
                XmlNode xn = xe.SelectSingleNode("//" + nodeName);
                if (xn != null)
                {
                    xn.InnerText = nodeValue;
                    flag = true;
                }
            }

            return flag;
        }

        public static string GetNodeInfoByNodeName(string path, string nodeName)
        {
            string xmlString = "";
            XmlDocument xml = new XmlDocument();
            xml.Load(path);
            var root = xml.DocumentElement;
            if (root != null)
            {
                var node = root.SelectSingleNode("//" + nodeName);
                if (node != null)
                {
                    xmlString = node.InnerText;
                }
            }
            return xmlString;
        }

        /// <summary>
        /// 根据xml路径获取DataSet。如果Table名为空：flag=false 返回所有xml的数据；flag=true 将xml中的table名作为数据项返回。否则根据table名获取相应的table信息返回。
        /// </summary>
        /// <param name="xmlPath">
        /// 	xml文件路径
        /// 	xml文件路径
        /// </param>
        /// <param name="tableName">
        /// 	所要获取的Table名，可为空
        /// 	所要获取的Table名，可为空
        /// </param>
        /// <param name="flag">
        /// 	若为true，则只将所有表名作为数据项返回；若为false，则返回所要获取的Table的所有数据
        /// 	若为true，则只将所有表名作为数据项返回；若为false，则返回所要获取的Table的所有数据
        /// </param>
        /// <returns>返回所获取的DataSet</returns>
        /// <summary>
        /// 根据xml路径获取DataSet。如果Table名为空：flag=false 返回所有xml的数据；flag=true 将xml中的table名作为数据项返回。否则根据table名获取相应的table信息返回。
        /// </summary>
        /// <returns>返回所获取的DataSet</returns>
        public static DataSet GetTableByXml(string xmlPath, string tableName, bool flag)
        {
            DataSet ds = new DataSet();
            if (tableName == "")
            {
                DataSet ds1 = new DataSet();
                ds1.ReadXml(xmlPath);
                if (ds1.Tables.Count > 0)
                {
                    if (flag)
                    {
                        DataTable dt = new DataTable("typeTable");
                        dt.Columns.Add("TableName", typeof(string));
                        ds.Tables.Add(dt);
                        for (int i = 0; i < ds1.Tables.Count; i++)
                        {
                            DataRow dr = dt.NewRow();
                            dr["TableName"] = ds1.Tables[i].TableName;
                            ds.Tables["typeTable"].Rows.Add(dr);
                        }
                    }
                    else
                    {
                        ds = ds1.Copy();
                    }
                }
            }
            else
            {
                DataSet ds2 = new DataSet();
                ds2.ReadXml(xmlPath);
                if (ds2.Tables[tableName] != null)
                {
                    ds.Tables.Add(ds2.Tables[tableName].Copy());
                }
            }
            return ds;
        }

        public static string Replaceinvalid(string str)
        {
            System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex("[\x00-\x08|\x0b-\x0c|\x0e-\x1f]");
            return r.Replace(str, " ");
        }

        public static string GetInterfaceErrorString(string errCode)
        {
            #region
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append("<?xml version=\"1.0\" encoding=\"GB2312\"?>");
            sb.Append("<Root>");
            sb.Append("<Result><return_result>" + errCode + "</return_result></Result>");
            sb.Append("</Root>");

            return sb.ToString();
            #endregion
        }

        /// <summary>
        /// 插入新的XML数据到文档
        /// </summary>
        /// <param name="xmlPath">xml文件路径</param>
        /// <param name="arg">所要插入的内容</param>
        /// <returns>成功返回1，否则返回0</returns>
        public static int WriteXml(string xmlPath, string[] arg)
        {
            DataSet ds = new DataSet();

            //读取XML数据
            ds.ReadXml(xmlPath);

            //增加新行
            var r = ds.Tables[0].NewRow();
            ds.Tables[0].Rows.Add(r);

            //编辑新行的内容,插入用户提供的数据
            int rr = ds.Tables[0].Rows.Count - 1;
            ds.Tables[0].Rows[rr].BeginEdit();
            for (int i = 0; i <= arg.GetUpperBound(0); i++)
                ds.Tables[0].Rows[rr][i] = arg[i];
            ds.Tables[0].Rows[rr].EndEdit();

            try
            {
                //利用数据集更新XML文档
                ds.WriteXml(xmlPath);
            }
            catch
            {
                return 0;
            }
            return 1;
        }
    }
}
